import {WebSocketMessage} from "@/types/webSocketMessageTypes";
import {WebSocketMessageType} from "@/enums/webSocketEnum";
import router from "@/router";

export class WebSocketClient {
    private readonly url: string;
    private ws: WebSocket;
    // 重连尝试次数
    private reconnectAttempts: number = 0;
    // 最大重连次数（设为Infinity表示无限重连）
    private readonly maxReconnectAttempts: number = 8;
    // 重连间隔（使用指数退避）
    private readonly baseReconnectInterval: number = 1000;
    // 心跳间隔（建议小于服务端超时时间）
    private readonly heartbeatInterval: number = 30000;
    // 心跳超时时间（需服务端在该时间内返回响应）
    private readonly heartbeatTimeout: number = 10000;
    // 心跳定时器
    private heartbeatTimer: NodeJS.Timeout;
    // 心跳超时检测定时器
    private heartbeatTimeoutTimer: NodeJS.Timeout;

    private chatInfoStore: any;

    private systemStore: any;

    constructor(url: string, chatInfoStore: any, systemStore: any) {
        this.url = url;
        this.chatInfoStore = chatInfoStore;
        this.systemStore = systemStore;
    }

    // 初始化连接
    connect() {
        // 防止重复创建
        if (this.ws) {
            this.ws.close();
        }

        this.ws = new WebSocket(this.url);


        // 监听WebSocket事件
        this.ws.onopen = () => {
            console.debug(`WebSocket connected`);
            // 重置重连次数
            this.reconnectAttempts = 0;
            this.systemStore.systemClosed = false;
            this.startHeartbeat();
        };

        this.ws.onmessage = (messageEvent: MessageEvent) => {
            let messageJson: WebSocketMessage = JSON.parse(messageEvent.data);
            switch (messageJson.type) {
                case WebSocketMessageType.USER_INFO:
                    this.chatInfoStore.chatUser = messageJson.data;
                    break;
                case WebSocketMessageType.USER_MESSAGE:
                    let id = messageJson.data.id;
                    if (id < this.chatInfoStore.userMessages.length && messageJson.data.from === this.chatInfoStore.chatUser.chatUserId) {
                        this.chatInfoStore.userMessages[id] = messageJson.data;
                    } else {
                        this.chatInfoStore.userMessages.push(messageJson.data);
                    }
                    this.chatInfoStore.chatUser.content++;
                    break;
                case WebSocketMessageType.HEARTBEAT:
                    this.resetHeartbeat();
                    break;
                case WebSocketMessageType.CLOSE:
                    if (!this.systemStore.systemClosed) {
                        this.toClose();
                        this.disconnect();
                    }
                    break;
                default:
                    console.log('接收到消息', messageEvent.data);
            }
        };


        this.ws.onerror = (error) => {
            console.error('WebSocket error:', error);
            // 错误时关闭连接，触发重连
            this.ws.close();
        };

        this.ws.onclose = (event) => {
            console.debug(`WebSocket closed, code: ${event.code}, reason: ${event.reason}`);
            this.stopHeartbeat();

            // 系统关闭
            if (this.systemStore.systemClosed) {
                return;
            }

            if (this.reconnectAttempts >= this.maxReconnectAttempts) {
                this.toClose();
                return;
            }

            this.scheduleReconnect();
        };
    }

    reconnect() {
        const socket = new WebSocket(this.url);
        socket.onopen = this.ws.onopen;
        socket.onmessage = this.ws.onmessage;
        socket.onerror = this.ws.onerror;
        socket.onclose = this.ws.onclose;
        this.ws = socket;
    }

    // 启动心跳检测
    startHeartbeat() {
        this.heartbeatTimer = setInterval(() => {
            // 确保连接状态为OPEN
            if (this.ws?.readyState === WebSocket.OPEN) {
                const webSocketMessage: WebSocketMessage = {
                    type: WebSocketMessageType.HEARTBEAT,
                    data: new Date().getTime()
                }
                console.debug(webSocketMessage.data, `发送${WebSocketMessageType.HEARTBEAT}`)
                this.ws.send(JSON.stringify(webSocketMessage));
                // 设置超时检测
                this.heartbeatTimeoutTimer = setTimeout(() => {
                    console.debug('心跳检测超时，断开连接', new Date().getTime());
                    this.ws.close(); // 触发重连
                }, this.heartbeatTimeout);
            }
        }, this.heartbeatInterval);
    }

    // 重置心跳超时检测
    resetHeartbeat() {
        clearTimeout(this.heartbeatTimeoutTimer);
    }

    // 停止心跳检测
    stopHeartbeat() {
        clearInterval(this.heartbeatTimer);
        clearTimeout(this.heartbeatTimeoutTimer);
        this.heartbeatTimer = null;
        this.heartbeatTimeoutTimer = null;
    }

    // 安排重连（指数退避）
    scheduleReconnect() {
        const delay = this.baseReconnectInterval * Math.pow(2, this.reconnectAttempts);
        this.reconnectAttempts++;
        console.debug(`${delay}ms 后进行第${this.reconnectAttempts}次重连`);
        setTimeout(() => this.reconnect(), delay);
    }

    disconnect() {
        this.ws.close(1000, '主动断开连接');
    }

    private toClose() {
        this.systemStore.systemClosed = true;
        router.push("/close");
    }
}
